package com.diaohaiwen.framework.web.interceptor;

import com.diaohaiwen.common.log.BaseLogSend;
import com.diaohaiwen.common.log.OperatorLog;
import com.diaohaiwen.common.obj.cache.RequestCache;
import com.diaohaiwen.common.obj.log.RequestLog;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static com.diaohaiwen.common.constant.RequestConstant.*;
import static com.diaohaiwen.common.obj.cache.RequestCache.*;

/**
 * @author 刁海文
 * @Remark Request 链路拦截操作
 * @since 2022/8/8 9:28
 */
@Component
public class WebMvcInterceptor implements HandlerInterceptor {

    private final Logger logger = LoggerFactory.getLogger("Web Mvc Interceptor");
    @Autowired(required = false)
    BaseLogSend baseLogSend;

    @Override
    public boolean preHandle(@Nullable HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Object handler) {
        assert request != null;

        String requestId = request.getHeader(REQUEST_ID);
        String linkId = request.getHeader(LINK_ID);
        String authority = request.getHeader(AUTHORITY);

        initializationBase(requestId, linkId, authority);

        initializationOperatorLog(handler);
        if (!isEnable()) {
            return false;
        }

        setRequestInfo(request);

        return true;
    }

    @Override
    public void afterCompletion(@Nullable HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Object handler, Exception ex) {
        RequestLog cache = RequestCache.getThreadLocal();
        long startTime = RequestCache.getStartTime();
        long endTime = System.currentTimeMillis();
        logger.info("""
                ==============================================================================
                Method   :[{}_{}]
                Parameter:[{}]
                User     :[{}]
                Duration :[{}] ms
                ==============================================================================
                """, cache.getMethod(), cache.getUri(), cache.getRequestBody(), RequestCache.getLoginUser().console(), endTime - startTime);
        RequestCache.clear();
        if (baseLogSend != null) {
            // 发送日志
            baseLogSend.executeHTTP(cache);
        }
    }


    // 链路日志初始化
    private void initializationOperatorLog(Object handler) {
        HandlerMethod method = (HandlerMethod) handler;
        OperatorLog log = Optional.ofNullable(method.getMethodAnnotation(OperatorLog.class))
                .orElseGet(() -> method.getBeanType().getAnnotation(OperatorLog.class));

        RequestCache.initializationOperatorLog(log);
    }

    private void setRequestInfo(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> object = new HashMap<>();
        parameterMap.forEach((name, value) -> {
            if (value.length == 1) {
                object.put(name, value[0]);
            } else {
                object.put(name, value);
            }
        });

        putRequestRemote(request.getMethod(), request.getRequestURI(), getDescribe(), object);

    }

}
